package io.dcloud.uniplugin.utils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import io.dcloud.feature.uniapp.AbsSDKInstance;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.uniplugin.bc.DeviceWrapper;
import io.dcloud.uniplugin.bc.TrainActivity;
import io.dcloud.uniplugin.bc.TrainEntryActivity;
import tech.brainco.crimsonsdk.BrainWave;
import tech.brainco.crimsonsdk.CrimsonDevice;
import tech.brainco.crimsonsdk.CrimsonDeviceListener;
import tech.brainco.crimsonsdk.CrimsonDeviceScanListener;
import tech.brainco.crimsonsdk.CrimsonError;
import tech.brainco.crimsonsdk.CrimsonPermissions;
import tech.brainco.crimsonsdk.CrimsonSDK;
import tech.brainco.crimsonsdk.DeviceInfo;
import tech.brainco.crimsonsdk.EEG;
import tech.brainco.crimsonsdk.IMU;
import tech.brainco.trainsdk.BcTrainPlugin;
import tech.brainco.trainsdk.api.BcTrainDeviceListener;
import tech.brainco.trainsdk.api.BcTrainLoadListListener;
import tech.brainco.trainsdk.api.BcTrainModuleInitListener;
import tech.brainco.trainsdk.api.device.BcDeviceListener;
import tech.brainco.trainsdk.api.device.BcDeviceWrapper;
import tech.brainco.trainsdk.model.BcTrainInfo;
import tech.brainco.trainsdk.utils.BcLogger;

public class BluetoothScanMgr {

    private static final String TAG = "BluetoothScanMgr";
    public static BluetoothScanMgr instance;
    private Context myContext = null;
    private AbsSDKInstance myUniSDKInstance = null;
    private static Gson gson = new Gson();
    private List<CrimsonDevice> devices = new ArrayList<>();
    private CrimsonDevice targetDevice = null;
    private BcTrainDeviceListener deviceListener = null;

    // 私有构造方法，确保外部无法直接创建实例
    private BluetoothScanMgr(Context context, AbsSDKInstance mUniSDKInstance) {
        myContext = context;
        myUniSDKInstance = mUniSDKInstance;
        CrimsonSDK.setLogLevel(CrimsonSDK.LogLevel.INFO);
        CrimsonSDK.registerBLEStateReceiver(context);
        Log.d(TAG, "BluetoothScanMgr initialized");
    }


    // 提供静态方法来获取唯一实例
    public static synchronized BluetoothScanMgr getInstance(Context context, AbsSDKInstance mUniSDKInstance) {
        // 如果实例不存在，才创建
        if (instance == null) {
            instance = new BluetoothScanMgr(context, mUniSDKInstance);
        }
        return instance;
    }


    // 2. 启动蓝牙扫描
    public void startScan(UniJSCallback callback) {
        JSONObject data = new JSONObject();
        data.put("event", "startScan");


        if (instance == null || myContext == null) {

            Log.d(TAG, "instance==null||myContext==null");
            data.put("code", "-1");
            data.put("msg", "instance==null||myContext==null");
            callback.invoke(data);

            return;
        }
        if (CrimsonSDK.isScanning) {
            Log.d(TAG, "isScanning");
            CrimsonSDK.stopScan();
            data.put("code", "-1");
            data.put("msg", "isScanning");
            callback.invoke(data);

            return;
        }

        if (!CrimsonPermissions.checkBluetoothFeature(myContext)) {
            Log.d(TAG, "BLE not supported");
            data.put("code", "-1");
            data.put("msg", "BLE not supported");
            callback.invoke(data);

            return;
        }

//        BluetoothAdapter adapter = ((BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
//        if (adapter == null || !adapter.isEnabled()) {
//            CrimsonPermissions.enableBluetooth(this);
//            return;
//        }

        // location Permission
        if (!CrimsonPermissions.checkPermissions(myContext)) {
            Log.d(TAG, "myContext instanceof Activity=>" + (myContext instanceof Activity));

            CrimsonPermissions.requestPermissions((Activity) myContext);
            data.put("code", "-1");
            data.put("msg", "checkPermissions");
            callback.invoke(data);

            return;
        }

        CrimsonSDK.startScan(new CrimsonDeviceScanListener() {
            @Override
            public void onBluetoothAdapterStateChange(int state) {
                Log.i(TAG, "BluetoothAdapter state=" + state);
                switch (state) {
                    case BluetoothAdapter.STATE_ON:
                        //todo restart scan 为啥调用自己？
                        startScan(callback);
                        break;
                    case BluetoothAdapter.STATE_OFF:
                        CrimsonSDK.stopScan();
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void onFoundDevices(List<CrimsonDevice> results) {
                devices = results;
                Log.d(TAG, "onFoundDevices=>" + results);

//        CrimsonDeviceJson        {"batteryLevel":-1,"bleDevice":{},"centerContact":false,"connectivity":3,"firmwareRevision":"","hardwareRevision":"","hasCreateNotification":false,"manufacturerName":"","modelNumber":"","rssi":-65,"scanRecord":{"advertiseFlags":6,"bytes":[2,1,6,2,10,0,6,-1,66,82,100,0,3,11,9,66,89,49,49,45,50,65,53,66,53,17,7,-87,87,92,-59,-11,-92,-24,-107,-69,77,111,-46,1,0,116,13],"deviceName":"BY11-2A5B5","manufacturerSpecificData":{},"serviceUuids":[{}],"txPowerLevel":0},"serialNumber":"","sideContact":false}
                Gson gson1 = new Gson();
                data.put("code", "1");
//                todo gson为什么报错？
//                data.put("Devices", gson1.toJson(results));
                Log.d(TAG, "onFoundDevices=>invoke data" + data);


                callback.invoke(data);

                JSONObject params = new JSONObject();
                params.put("type", "onFoundDevices");
//                params.put("data", results);

                Map map = new HashMap<>();
                map.put("list", results);
                myUniSDKInstance.fireGlobalEventCallback("onFoundDevices", map);

//                doConnect("BY11-2A5B5");


            }

            @Override
            public void onError(CrimsonError error) {
                Log.d(TAG, "onFoundDevicesErr=>" + error.toString());
                data.put("code", "0");
//                data.put("err", gson.toJson(error));
                callback.invoke(data);

            }
        }, null);
    }

    // 3. 停止蓝牙扫描
    public void stopScan(UniJSCallback callback) {

        if (CrimsonSDK.isScanning) {
            CrimsonSDK.stopScan();

        }
        JSONObject data = new JSONObject();
        data.put("event", "stopScan");
        data.put("code", "1");
        if (callback != null) {
            callback.invoke(data);
        }
    }

    public void stopScan() {
        if (CrimsonSDK.isScanning) {
            CrimsonSDK.stopScan();

        }
    }

    public void doConnect(String deviceName) {

        // 判断 devices 不为 null 并且不为空
        if (devices != null && !devices.isEmpty()) {
            // 遍历 devices 列表，查找 id = "xxx" 的设备
            for (CrimsonDevice device : devices) {
                if (device.getName().equals(deviceName)) {
                    targetDevice = device;
                    break; // 找到之后退出循环
                }
            }
        }

        // 如果找到了目标设备，可以在这里使用 targetDevice
        if (targetDevice != null) {
            // 找到了设备，可以执行相应的操作
            Log.d(TAG, "Found device with ID1: " + targetDevice.getName());

            if (BcTrainPlugin.getInstance().isInited()) {
                //注意要等初始化完成再调用BcTrainPlugin.getInstance()的其他方法
                BcTrainPlugin.getInstance().loadTrainList(new BcTrainLoadListListener() {
                    @Override
                    public void onSuccess(List<BcTrainInfo> list) {

                    }

                    @Override
                    public void onError(@NonNull String s, @Nullable String s1, @Nullable Object o) {

                    }
                });
            } else {
                BcTrainPlugin.getInstance().init(myContext.getApplicationContext(), "shandongtejiao_mi66QcwfevYfJbVLkcDJNuNkvLCHvFtj", new BcTrainModuleInitListener() {
                    @Override
                    public void onInited() {
                        Log.e(TAG, " BcTrainPlugin onInited");
                    }

                    @Override
                    public void onError(String s) {

                    }
                });

            }

            BcDeviceWrapper deviceWrapper = new DeviceWrapper(targetDevice);
            deviceListener = BcTrainPlugin.getInstance().createDeviceListener(deviceWrapper);
            DeviceListener listener = new DeviceListener(deviceListener);
            targetDevice.setListener(listener);
//                todo 为什么使用这个myContext就报错？
            targetDevice.connect(myContext);

        } else {
            // 没有找到对应的设备
            Log.d(TAG, "Device with ID " + deviceName + " not found");
        }
    }

    /**
     * 断开连接
     */
    public void doDisconnect() {
        // 如果找到了目标设备，可以在这里使用 targetDevice
        if (targetDevice != null) {
            // 找到了设备，可以执行相应的操作
            Log.e(TAG, "Disconnect Found device with ID1: " + targetDevice.getName());
            targetDevice.disconnect();
        }
    }

    public void startGame(int courseId, int stage, boolean withIntro, int duration, int bestScore) {
        Log.d(TAG,"startGame");
        Log.d(TAG, new StringBuilder()
                .append(courseId).append(stage).append(withIntro).append(duration).append(bestScore)
                .toString());
        //1 检查头环是否佩戴 2跳转训练页面
        if (!BcTrainPlugin.getInstance().isInited()) {
            Toast.makeText(myContext, "模块未初始化完成", Toast.LENGTH_SHORT).show();
            return;
        }
        if (deviceListener == null) {
            Toast.makeText(myContext, "deviceListener=null", Toast.LENGTH_SHORT).show();
            return;
        }
        if (!deviceListener.isContacted()) {
            Toast.makeText(myContext, "头环未佩戴", Toast.LENGTH_SHORT).show();
            return;
        }


//        BcTrainInfo info = new BcTrainInfo("神秘森林", 10116, "https://focus-xin.brainco.cn/course/banner/large/10116_new.png", 1);
        Intent intent = new Intent(myContext, TrainActivity.class);
        intent.putExtra("courseId", courseId);
        intent.putExtra("stage", stage);
        intent.putExtra("withIntro", withIntro);
        intent.putExtra("duration", duration);
        intent.putExtra("bestScore", bestScore);

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        myContext.startActivity(intent);
    }

    public void doPair() {
        if (targetDevice == null) {
            Log.d(TAG, "targetDevice is null ");

            return;
        }

        if (!targetDevice.isConnected()) {
            Log.d(TAG, "Must be connected before pair");

            return;
        }

        if (targetDevice.isInPairingMode()) {
            // 在配对模式，执行配对操作
            targetDevice.pair(error -> {
                if (error == null) {
                    startEEG(); // 配对成功后启动 EEG
                } else {
                    Log.d(TAG, "pair失败1" + error.toString());
                }
            });
        } else if (targetDevice.isInNormalMode()) {
            // 如果设备是正常模式，进行配对信息验证
            targetDevice.validatePairInfo(error -> {
                if (error == null) {
                    startEEG(); // 配对成功后启动 EEG
                } else {
                    Log.d(TAG, "pair失败2" + error.toString());
                }
            });
        } else {
            Log.d(TAG, "Unknown device mode");

        }
    }

    public void startEEG() {
        if (targetDevice == null) {
            Log.d(TAG, "targetDevice is null ");

            return;
        }
        targetDevice.startEEGStream(error -> {
            if (error != null) {
                Log.i(TAG, "startEEGStream:" + error.getCode() + ", message=" + error.getMessage());
            } else {
                Log.i(TAG, "startEEGStream success");

                // NOTE: start imu if need check device orientation
//                startIMU();

                targetDevice.startIMU(err -> {
                    if (err != null) {
                        Log.i(TAG, "startIMU:" + err.getCode() + ", message=" + err.getMessage());
                    } else {
                        Log.i(TAG, "startIMU success");
                    }
                });
            }
        });
    }


    private class DeviceListener extends CrimsonDeviceListener {
        final BcDeviceListener listener;

        @Override
        public void onError(CrimsonError error) {
            Map map = new HashMap<>();
            map.put("error", error);
            myUniSDKInstance.fireGlobalEventCallback("onError", map);
//            super.onError(error);
        }

        @Override
        public void onDeviceInfoReady(DeviceInfo info) {
            Map map = new HashMap<>();
            map.put("info", info);
            myUniSDKInstance.fireGlobalEventCallback("onDeviceInfoReady", map);
//            super.onDeviceInfoReady(info);
        }

        @Override
        public void onBatteryLevelChange(int batteryLevel) {
            Map map = new HashMap<>();
            map.put("batteryLevel", batteryLevel);
            myUniSDKInstance.fireGlobalEventCallback("onBatteryLevelChange", map);
//            super.onBatteryLevelChange(batteryLevel);
        }

        public DeviceListener(BcDeviceListener listener) {
            this.listener = listener;
        }

        @Override
        public void onConnectivityChange(int connectivity) {
            Log.e(TAG, "onConnectivityChange:" + connectivity);
            if (myUniSDKInstance != null) {
                Map map = new HashMap<>();
                map.put("result", connectivity);
                myUniSDKInstance.fireGlobalEventCallback("onConnectivityChange", map);
            }else {
                Log.e(TAG, "onConnectivityChange:" + "myUniSDKInstance=null");

            }

            if (connectivity == CrimsonSDK.Connectivity.CONNECTED) {
                Log.e(TAG, "onConnectivityChange: doPair");
                doPair();
            }

            listener.onConnectivityChange(connectivity);
        }

        @Override
        public void onContactStateChange(int state) {
            if (myUniSDKInstance != null) {
                Map map = new HashMap<>();
                map.put("result", state);
                myUniSDKInstance.fireGlobalEventCallback("onContactStateChange", map);
            }
            Log.e(TAG, "onContactStateChange:==========> " + state);
            listener.onContactStateChange(state);
        }

        @Override
        public void onOrientationChange(int orientation) {
            if (myUniSDKInstance != null) {
                Map map = new HashMap<>();
                map.put("result", orientation);
                myUniSDKInstance.fireGlobalEventCallback("onOrientationChange", map);
            }
            listener.onOrientationChange(orientation);
        }

        @Override
        public void onAttention(float attention) {

            if (myUniSDKInstance != null) {
                Map map = new HashMap<>();
                map.put("result", attention);
                myUniSDKInstance.fireGlobalEventCallback("onAttention", map);
            }
            listener.onAttention(attention);
        }

        @Override
        public void onMeditation(float meditation) {
            if (myUniSDKInstance != null) {
                Map map = new HashMap<>();
                map.put("result", meditation);
                myUniSDKInstance.fireGlobalEventCallback("onMeditation", map);
            }
            listener.onMeditation(meditation);
        }
    }

}
